#pragma once
#include <string>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include "Log.hpp"
#include <netinet/in.h>
#include <arpa/inet.h>
#include "InetAddr.hpp"
#include <unistd.h>
const static int gbacklog = 8;
class TcpServer
{
    public:
    TcpServer(uint16_t port) : _port(port),_isrunning(false)
    {
    }

    void Service(int sockfd,InetAddr client)
    {
        LOG(DEBUG,"get a new link,info %s:%d,fd:%d\n",client.Ip().c_str(),client.Port(),sockfd);
        std::string clientaddr = "[" + client.Ip() + ":" + std::to_string(client.Port()) + "]#";
        while(true)
        {
            char inbuffer[1024];
            std::string response = clientaddr;
            ssize_t n = recv(sockfd,inbuffer,sizeof(inbuffer),0);
            if(n > 0)
            {
                response += inbuffer;
                send(sockfd,response.c_str(),1024,0);
            }
            else if(n == 0)
            {
                close(sockfd);
            }
            else
            {
                LOG(ERROR,"recv error!\n");
                break;
            }
        }
    }
    void Loop()
    {
        _isrunning = true;
        while(_isrunning)
        {
            sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listensock,reinterpret_cast<sockaddr*>(&peer),&len);
            if(sockfd < 0)
            {
                LOG(WARNING,"get socket link error!\n");
                continue;
            }
            pid_t id = fork();
            if(id ==0)
            {
                if(fork() > 0) exit(0);
                Service(sockfd,peer);
            }
            else 
            {
                close(sockfd);
            }
        }
        _isrunning = false;
    }
    void InitServer()
    {
        // 创建套接字
        _listensock = socket(AF_INET,SOCK_STREAM,0);
        if(_listensock < 0)
        {
            LOG(FATAL,"create socket error!\n");
            exit(-1);
        }
        LOG(INFO,"create socket success!\n");

        //绑定套接字
        sockaddr_in addr;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(_port);
        addr.sin_family = AF_INET;
        int n = bind(_listensock,reinterpret_cast<sockaddr*>(&addr),sizeof(addr));
        if(n < 0)
        {
            LOG(ERROR,"Server Bind Error!\n");
            exit(-2);
        }
        LOG(INFO,"Server Bind Success!\n");
        //监听
        n = listen(_listensock,gbacklog);
        if(n < 0)
        {
            LOG(ERROR,"Set Listen Error!\n");
            exit(-3);
        }
        LOG(INFO,"Set Listen Success!\n");
        

    }

private:
    std::string _ip;
    uint16_t _port;
    int _listensock;
    bool _isrunning;
};